
<#
param()

. {
	[CmdletBinding(SupportsShouldProcess = $false,
		SupportsTransactions = $false,
		ConfirmImpact = "None",
		DefaultParameterSetName = "")]
    param(
		[Parameter(Position = 0)]
        [String]
        $ConfigurationPath = ""
    )

} @args
#>

Import-Module -Name PSProvider -Version 0.3

#########################
## Cleanup
#########################

$Module = $MyInvocation.MyCommand.ScriptBlock.Module 
$Module.OnRemove = {Remove-PSDrive iso}


#########################
## Private properties
#########################




#########################
## Public properties
#########################




#########################
## Functions
#########################

Function New-IsoStorageProvider {
    [CmdletBinding()]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]$DriveName
        ,
        [ValidateSet("User","Machine")]
        [String]$Scope = "User"
    )

    process {
        New-Module -Name "${DriveName}Impl" -Args $Scope,$DriveName -ScriptBlock {
            param(
                [String]$InternalScope
                ,
                [String]$DriveName
            )


            function GetIsoStorage {
                [CmdletBinding()]
                param(
                    [ValidateSet("User","Machine")]
                    [String]$scope = $InternalScope
                )

                $psprovider.WriteVerbose("GetIsoStorage: $scope")
                switch ($scope) {
                    'User' {[System.IO.IsolatedStorage.IsolatedStorageFile]::GetUserStoreForAssembly()}
                    'Machine' {[System.IO.IsolatedStorage.IsolatedStorageFile]::GetMachineStoreForAssembly()}
                }
            }
            function NewIsoRootObject {
                [CmdletBinding()]
                param()

                ## TODO: Add more members if .NET 4 available
                $IsoStorage = GetIsoStorage
                NewIsoObject "IsolatedStorage.DriveInfo" @{"Name"=$DriveName; "Root"="${DriveName}:\";
                    "Used"=($IsoStorage.CurrentSize); "Free"=($IsoStorage.MaximumSize - $IsoStorage.CurrentSize)}
            }
            function NewIsoDirectoryObject {
                [CmdletBinding()]
                param([String]$path, [String]$name)

                ## TODO: Add more members if .NET 4 available
                NewIsoObject "IsolatedStorage.DirectoryInfo" @{"FullName"=(Join-Path "iso:$path" $name); "Name"=$name}
            }
            function NewIsoFileObject {
                [CmdletBinding()]
                param([String]$path, [String]$name)

                ## TODO: Add more members if .NET 4 available
                NewIsoObject "IsolatedStorage.FileInfo" @{"FullName"=(Join-Path "iso:$path" $name); "Name"=$name}
            }
            function NewIsoObject {
                [CmdletBinding()]
                param(
                    [String]$typeName
                    ,
                    [Hashtable]$properties
                )

                $Object = New-Object PSObject -Property $properties
                $Object.PSObject.TypeNames.Insert(0, $typeName)
                $Object
            }


            ##
            ## ItemCmdletProvider
            ##
            function ClearItem {
                [CmdletBinding()]
                param([String]$path)

                $psprovider.WriteVerbose("ClearItem: $path")
                $Exception = New-Object System.Management.Automation.PSNotSupportedException ($PSCmdlet.GetResourceString("SessionStateStrings", "CmdletProvider_NotSupported"))
                throw $Exception
                ## TODO: Improve error
            }
            function GetItem {
                [CmdletBinding()]
                param([String]$path)

                $psprovider.WriteVerbose("GetItem: $path")

                ## TODO: Move this to a private function for reuse
                if ($path -match '\\$') {
                    $DirectoriesOnly = $true
                    $path = $path -replace '\\$'  ## remove trailing slash
                }
                if ($path -notmatch '^\\') {
                    $path = "\$path"
                }
                $IsoStorage = GetIsoStorage
                foreach ($d in $IsoStorage.GetDirectoryNames($path)) {
                    $Directory = NewIsoDirectoryObject (Split-Path $path) $d
                    $psprovider.WriteVerbose("GetItem: Found Directory")
                    $psprovider.WriteItemObject($Directory, $Directory.FullName, $true)
                }
                if (-not $DirectoriesOnly) {
                    foreach ($f in $IsoStorage.GetFileNames($path)) {
                        $File = NewIsoFileObject (Split-Path $path) $f
                        $psprovider.WriteVerbose("GetItem: Found File")
                        $psprovider.WriteItemObject($File, $File.FullName, $false)
                    }
                }
            }
            function InvokeDefaultAction {
                [CmdletBinding()]
                param([String]$path)

                $psprovider.WriteVerbose("InvokeDefaultAction: $path")
                $Exception = New-Object System.Management.Automation.PSNotSupportedException ($PSCmdlet.GetResourceString("SessionStateStrings", "CmdletProvider_NotSupported"))
                throw $Exception
                ## TODO: Improve error
            }
            function IsValidPath {
                [CmdletBinding()]
            	[outputtype('bool')]
                param([String]$path)

                $psprovider.WriteVerbose("IsValidPath: $path")

                ## TODO: Improve
                $true
            }
            function ItemExists {
                [CmdletBinding()]
            	[outputtype('bool')]
                param([String]$path)

                $psprovider.WriteVerbose("ItemExists: $path")

                $path = $path -replace '\\$'  ## remove trailing slash
                if ($path -notmatch '^\\') {
                    $path = "\$path"
                }
                $IsoStorage = GetIsoStorage
                if ($path -eq "\") {
                    $true
                } elseif ($IsoStorage.GetDirectoryNames($path)) {
                    $true
                } elseif ($IsoStorage.GetFileNames($path)) {
                    $true
                } else {
                    $false
                }
            }
            function SetItem {
                [CmdletBinding()]
                param([String]$path, [Object]$value)

                $psprovider.WriteVerbose("SetItem: $path")
                $Exception = New-Object System.Management.Automation.PSNotSupportedException ($PSCmdlet.GetResourceString("SessionStateStrings", "CmdletProvider_NotSupported"))
                throw $Exception
                ## TODO: Improve error
            }


            ##
            ## ContainerCmdletProvider
            ##
            function CopyItem {
                [CmdletBinding()]
                param([String]$path, [String]$copyPath, [Bool]$recurse)

                ## TODO: Support should process

                $psprovider.WriteVerbose("CopyItem: $path, $copyPath, $recurse")
                # ...
            }
            function GetChildItems {
                [CmdletBinding()]
                param([String]$path, [Bool]$recurse)

                $psprovider.WriteVerbose("GetChildItems: $path, $recurse")

                if ($recurse) {
                    ## TODO:
                } else {
                    if ($path -notmatch '\\$') {
                        $path = "$path\"
                    }
                    GetItem "$path*"
                }
            }
            function GetChildNames {
                [CmdletBinding()]
                param([String]$path, [System.Management.Automation.ReturnContainers]$returnContainers)

                $psprovider.WriteVerbose("GetChildNames: $path, $returnContainers")

                if ($path -notmatch '\\$') {
                    $path = "$path\"
                }
                $path = "$path*"
                $IsoStorage = GetIsoStorage
                if ($returnContainers -eq [System.Management.Automation.ReturnContainers]::ReturnMatchingContainers) {
                    foreach ($d in $IsoStorage.GetDirectoryNames($path)) {
                        $fullname = Join-Path (Split-Path $path) $d
                        $psprovider.WriteVerbose("GetChildNames: Found Directory")
                        $psprovider.WriteItemObject($d, $fullname, $true)
                    }
                } else {
                    ## TODO: Support ReturnAllContainers
                    foreach ($d in $IsoStorage.GetDirectoryNames($path)) {
                        $fullname = Join-Path (Split-Path $path) $d
                        $psprovider.WriteVerbose("GetChildNames: Found Directory")
                        $psprovider.WriteItemObject($d, $fullname, $true)
                    }
                }
                foreach ($f in $IsoStorage.GetFileNames($path)) {
                    $fullname = Join-Path (Split-Path $path) $f
                    $psprovider.WriteVerbose("GetChildNames: Found File")
                    $psprovider.WriteItemObject($f, $fullname, $false)
                }
            }
            function HasChildItems {
                [CmdletBinding()]
            	[outputtype('bool')]
                param([String]$path)

                $psprovider.WriteVerbose("HasChildItems: $path")

                if ($path -notmatch '\\$') {
                    $path = "$path\"
                }
                $path = "$path*"
                $IsoStorage = GetIsoStorage
                if ($IsoStorage.GetDirectoryNames($path)) {
                    $true
                } elseif ($IsoStorage.GetFileNames($path)) {
                    $true
                } else {
                    $false
                }
            }
            function NewItem {
                [CmdletBinding()]
                param(
            		[String]$path, 
            		[String]$itemTypeName, 
            		[Object]$newItemValue
                )

                ## TODO: Support should process?

                $psprovider.WriteVerbose("NewItem: $path, $itemTypeName, '$newItemValue'")

                if ($path -notmatch '^\\') {
                    $path = "\$path"
                }
                $IsoStorage = GetIsoStorage
                if ("Directory" -like "$itemTypeName*") {
                    $psprovider.WriteVerbose("NewItem: Creating directory '$path'")
                    $IsoStorage.CreateDirectory($path)
                } elseif ("File" -like "$itemTypeName*") {
                    $psprovider.WriteVerbose("NewItem: Want to create a file '$path'")
                    ## TODO:
                } else {
                    #New-Item : The type is not a known type for the file system. Only "file" and "directory" can be specified.
                    #+ New-Item <<<<  "testff" -ItemType "iii" -ver
                    #    + CategoryInfo          : InvalidArgument: (:) [New-Item], PSArgumentException
                    #    + FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.NewItemCommand
                    ## TODO: Throw error
                }
            }
            function RemoveItem {
                [CmdletBinding()]
                param([String]$path, [Bool]$recurse)

                ## TODO: Support should process

                $psprovider.WriteVerbose("RemoveItem: $path, $recurse")

                if ($path -notmatch '^\\') {
                    $path = "\$path"
                }
                $IsoStorage = GetIsoStorage
                if ($recurse) {
                    ## TODO:
                } else {
                    if ($IsoStorage.GetDirectoryNames($path)) {
                        $psprovider.WriteVerbose("RemoveItem: Deleting directory '$path'")
                        $IsoStorage.DeleteDirectory($path)
                    } elseif ($IsoStorage.GetFileNames($path)) {
                        $psprovider.WriteVerbose("NewItem: Want to delete a file '$path'")
                        ## TODO:
                    } else {
                        #New-Item : The type is not a known type for the file system. Only "file" and "directory" can be specified.
                        #+ New-Item <<<<  "testff" -ItemType "iii" -ver
                        #    + CategoryInfo          : InvalidArgument: (:) [New-Item], PSArgumentException
                        #    + FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.NewItemCommand
                        ## TODO: Throw error
                    }
                }
            }
            function RenameItem {
                [CmdletBinding()]
                param([String]$path, [String]$newName)

                ## TODO: Support should process

                $psprovider.WriteVerbose("RenameItem: $path, $newName")
                # ...
            }


            ##
            ## NavigationCmdletProvider
            ##
            function IsItemContainer {
                [CmdletBinding()]
            	[outputtype('bool')]
                param([String]$path)

                $psprovider.WriteVerbose("IsItemContainer: $path")

                $path = $path -replace '\\$'  ## remove trailing slash
                if ($path -notmatch '^\\') {
                    $path = "\$path"
                }
                $IsoStorage = GetIsoStorage
                if ($path -eq "\") {
                    $true
                } elseif ($IsoStorage.GetDirectoryNames($path)) {
                    $true
                } else {
                    $false
                }
            }
            function MoveItem {
                [CmdletBinding()]
                param([String]$path, [String]$destination)

                ## TODO: Support should process

                $psprovider.WriteVerbose("MoveItem: $path, $destination")
                # ...
            }
        }
    }
}


Function New-IsolatedStorageDrive {
    [CmdletBinding()]
    param(
        [Parameter(Position = 0, Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]$Name
        ,
        [ValidateSet("User","Machine")]
        [String]$Scope = "User"
    )

    process {
        New-PSDrive $Name TreeScriptProvider -Root / -Scope Global -ModuleInfo (New-IsoStorageProvider $Name -Scope $Scope)
    }
}


#########################
## Initialization
#########################

## Scope:  User + PowerShell (Assembly)
New-IsolatedStorageDrive "iso"




## Exported functions, variables, etc.
#$ExcludedFuctions = @("")
#$Functions = Get-Command "*-*" | Where-Object {$ExcludedFuctions -notcontains $_.Name}
Export-ModuleMember -Function "New-IsolatedStorageDrive" -Alias *
